#pragma once

#include "SPEmitter.h"

namespace SP
{
	//---------------------------------------------------------------------------



	//---------------------------------------------------------------------------
	class DLL_EXPORT SPOBJLoader
	{
	public:
		struct VERTEX
		{
			XMFLOAT3 position;
			XMFLOAT3 normal;
			XMFLOAT2 texcoord;
		};

		struct CacheEntry
		{
			UINT index;
			CacheEntry* pNext;
		};

		struct Material
		{
			WCHAR   strName[MAX_PATH];

			XMFLOAT3 vAmbient;
			XMFLOAT3 vDiffuse;
			XMFLOAT3 vSpecular;

			int nShininess;
			float fAlpha;

			bool bSpecular;

			WCHAR strTexture[MAX_PATH];
		};

	public:
		SPOBJLoader( const char* );
		SPOBJLoader( const WCHAR* );
		~SPOBJLoader();

		std::vector <VERTEX>*			GetVertices(){ return &m_Vertices; }
		std::vector <DWORD>*			GetIndices(){ return &m_Indices; }
		std::vector <Material*>*		GetMaterial(){ return &m_Materials; }
		std::vector <DWORD>*			GetAttributes(){ return &m_Attributes; }

	private:
		HRESULT			LoadGeometryFromOBJ( const WCHAR* strFileName );
		HRESULT			LoadMaterialsFromMTL( const WCHAR* strFileName );
		void					InitMaterial( Material* pMaterial );

		DWORD			AddVertex( UINT hash, VERTEX* pVertex );
		void					DeleteCache();

		std::vector <CacheEntry*>	m_VertexCache;	// Hashtable cache for locating duplicate vertices
		std::vector <VERTEX>			m_Vertices;			// Filled and copied to the vertex buffer
		std::vector <DWORD>			m_Indices;				// Filled and copied to the index buffer
		std::vector <DWORD>			m_Attributes;		// Filled and copied to the attribute buffer
		std::vector <Material*>			m_Materials;			// Holds material properties per subset

		WCHAR								m_strMediaDir[ MAX_PATH ];
	};

	//---------------------------------------------------------------------------




	//---------------------------------------------------------------------------
	class DLL_EXPORT SPStaticMesh
	{
	public:	
		struct SP_SM_MATERIAL
			{
				XMFLOAT3 vAmbient;
				XMFLOAT3 vDiffuse;
				XMFLOAT3 vSpecular;

				int nShininess;
				float fAlpha;

				bool bSpecular;
				bool bTexture;

				ID3D11Resource* pTexture;
				ID3D11ShaderResourceView* pTextureRV;
			};

			struct SP_SM_SUBSET
			{
				UINT IndexCount;
				UINT IndexStart;
				UINT VertexStart;

				UINT MaterialID;
			};
	public:
		SPStaticMesh();
		SPStaticMesh( SPOBJLoader* );
		~SPStaticMesh();

		UINT													GetVBStride()		{ return sizeof( SPOBJLoader::VERTEX ); }
		UINT													GetIndexCount()	{ return m_nIndexCount; };
		ID3D11Buffer*									GetVB()					{ return m_pVertexBuffer; }
		ID3D11Buffer*									GetIB()					{ return m_pIndexBuffer; }
		std::vector <SP_SM_SUBSET*>*			GetSubsets()			{ return &m_Subsets; }
		std::vector <SP_SM_MATERIAL*>*		GetMaterials()		{ return &m_Materials; }

		void CreateFileBuffer( SPFileBuffer* );
		void CreateFromFileBuffer( BYTE* );
	private:
		HRESULT Create( SPOBJLoader* );

		HRESULT CreateBuffer();

		void CreateMaterialFileBuffer( SPFileBuffer* );
		void CreateMaterialFromFileBuffer( BYTE* );

		UINT m_nVertexCount;
		UINT m_nIndexCount;

		ID3D11Buffer* m_pVertexBuffer;
		ID3D11Buffer* m_pIndexBuffer;

		SPOBJLoader::VERTEX* m_pVertices;
		DWORD* m_pIndices;

		std::vector <SP_SM_SUBSET*> m_Subsets;
		std::vector <SP_SM_MATERIAL*> m_Materials;
	};

	//---------------------------------------------------------------------------



	//---------------------------------------------------------------------------
	class DLL_EXPORT SPEmitterMesh : public SPEmitter
	{
	public:
		SPEmitterMesh();
		SPEmitterMesh( SPEmitterMesh* archetype, bool bDeepCopy = false );
		virtual ~SPEmitterMesh();

		void Create( SPEmitterMesh* archetype, bool bDeepCopy = false );
		void Create( const WCHAR* filename );

		virtual void Initialize();
		virtual void Render();	
		virtual void Advance( float fElapsedTime );
		virtual void ClearModule();
		virtual void CreateFileBuffer( SPFileBuffer* );
		virtual void CreateFromFileBuffer( BYTE* );
		//virtual bool SetSPModule( SPModule* pModule );

		void EnableTextureMapping( bool bMapping ){ m_bTextureMapping = bMapping; }
		void EnableLighting( bool bLighting ){ m_bLighting = bLighting; }
	protected:

		SPStaticMesh* m_pStaticMesh;

		bool m_bTextureMapping;
		bool m_bLighting;
		bool m_bReleaseaResouce;

		friend class SPEmitterMeshRenderer;
	};
}

